package com.zhang.common.util.object;

import com.google.common.collect.Lists;
import com.zhang.common.util.StringUtils;

import java.util.List;


import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 * ReflectUtils
 *
 * @author zhangxin
 * @date 2021/7/1
 */
public class ReflectUtils {
    private static Logger logger = LoggerFactory.getLogger(ReflectUtils.class);
    private static final String SETTER_PREFIX = "set";
    private static final String GETTER_PREFIX = "get";
    private static final String GETTER_PREFIX_BOOL = "is";
    private static final String CGLIB_CLASS_SEPARATOR = "$$";

    private ReflectUtils() {
    }

    public static String[] getFieldArray(Class clazz) {
        Field[] fields = clazz.getDeclaredFields();
        if (fields != null && fields.length > 0) {
            String[] array = new String[fields.length];

            for(int i = 0; i < fields.length; ++i) {
                array[i] = fields[i].getName();
            }

            return array;
        } else {
            return new String[0];
        }
    }

    public static List<String> getFieldList(Class clazz) {
        Field[] fields = clazz.getDeclaredFields();
        List<String> list = Lists.newArrayList();
        if (fields != null && fields.length > 0) {
            Field[] var3 = fields;
            int var4 = fields.length;

            for(int var5 = 0; var5 < var4; ++var5) {
                Field f = var3[var5];
                list.add(f.getName());
            }
        }

        return list;
    }

   /**
    * 得到实体类的数据库下划线格式的所有字段
    * @param clazz
    * @return java.util.List<java.lang.String>
    */
    public static List<String> getColumnList(Class clazz) {
        Field[] fields = clazz.getDeclaredFields();
        List<String> list = Lists.newArrayList();
        if (fields != null && fields.length > 0) {
            Field[] var3 = fields;
            int var4 = fields.length;

            for(int var5 = 0; var5 < var4; ++var5) {
                Field f = var3[var5];
                list.add(StringUtils.humpToLine(f.getName()));
            }
        }

        return list;
    }

    public static Object invokeGetter(Object obj, String fieldName) {
        Method method = getter(obj.getClass(), fieldName);

        try {
            if (method != null) {
                return method.invoke(obj);
            }
        } catch (Exception var4) {
            logger.error(String.format("反射调用 %s 报错, 错误信息:%s!", method.getName(), var4.getLocalizedMessage()), var4);
        }

        return null;
    }

    public static Method getter(Class clazz, String fieldName) {
        char[] chars = fieldName.toCharArray();
        chars[0] = (char)(chars[0] - 32);

        try {
            String getMethodName = "get" + chars;
            return clazz.getMethod(getMethodName);
        } catch (NoSuchMethodException var6) {
            try {
                String getMethodName = "is" + chars;
                return clazz.getMethod(getMethodName);
            } catch (NoSuchMethodException var5) {
                return null;
            }
        }
    }

    public static void invokeSetter(Object obj, String fieldName, Object value) {
        Method method = setter(obj.getClass(), fieldName);

        try {
            if (method != null) {
                method.invoke(obj, value);
            }
        } catch (Exception var5) {
            logger.error(String.format("反射调用 %s 报错, 错误信息:%s!", method.getName(), var5.getLocalizedMessage()), var5);
        }

    }

    public static Method setter(Class clazz, String fieldName) {
        try {
            Class[] parameterTypes = new Class[1];
            Field field = clazz.getDeclaredField(fieldName);
            parameterTypes[0] = field.getType();
            char[] chars = fieldName.toCharArray();
            chars[0] = (char)(chars[0] - 32);
            String methodName = "set" + chars;
            return clazz.getMethod(methodName, parameterTypes);
        } catch (Exception var6) {
            var6.printStackTrace();
            return null;
        }
    }

    public static <T> Class<T> getClassGenricType(final Class clazz) {
        return getClassGenricType(clazz, 0);
    }

    public static Class getClassGenricType(final Class clazz, final int index) {
        Type genType = clazz.getGenericSuperclass();
        if (!(genType instanceof ParameterizedType)) {
            logger.warn(clazz.getSimpleName() + "'s superclass not ParameterizedType");
            return Object.class;
        } else {
            Type[] params = ((ParameterizedType)genType).getActualTypeArguments();
            if (index < params.length && index >= 0) {
                if (!(params[index] instanceof Class)) {
                    logger.warn(clazz.getSimpleName() + " not set the actual class on superclass generic parameter");
                    return Object.class;
                } else {
                    return (Class)params[index];
                }
            } else {
                logger.warn("Index: " + index + ", Size of " + clazz.getSimpleName() + "'s Parameterized Type: " + params.length);
                return Object.class;
            }
        }
    }

    public static void main(String[] args) {
//        logger.info();
    }
}
